package cn.edu.dgut.css.sai.security.oauth2.client.userinfo;

import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiUserGetRequest;
import com.dingtalk.api.request.OapiUserGetUseridByUnionidRequest;
import com.dingtalk.api.response.OapiUserGetResponse;
import com.dingtalk.api.response.OapiUserGetUseridByUnionidResponse;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.taobao.api.ApiException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;

import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

/**
 * 暂时没有用
 *
 * @author sai
 * @since 2.1
 */
@SuppressWarnings("unused")
final class SaiDDH5OAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        // 使用钉钉开放平台SDK构造 OAuth2User
        // 1. 获取 userid ，https://ding-doc.dingtalk.com/doc#/serverapi2/ege851/602f4b15
        String userId = getDDUserId(userRequest);
        // 2. 获取 用户详情 ，https://ding-doc.dingtalk.com/doc#/serverapi2/ege851/AaRQe
        OapiUserGetResponse response = getDDUserInfo(userRequest, userId);
        // 3. 构造 Oauth2User
        return createDDOAuth2User(response);
    }

    private OAuth2User createDDOAuth2User(OapiUserGetResponse response) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            Map<String, Object> DDUserAttributes = objectMapper.readValue(response.getBody(), new TypeReference<>() {
            });
            Set<GrantedAuthority> authorities = new LinkedHashSet<>();
            authorities.add(new OAuth2UserAuthority(DDUserAttributes));
            return new DefaultOAuth2User(authorities, DDUserAttributes, "unionid");

        } catch (JsonProcessingException ex) {
            OAuth2Error oauth2Error = new OAuth2Error("invalid_OAuth2User_response",
                    "构造 OAuth2User 异常 : " + ex.getMessage(), null);
            throw new OAuth2AuthorizationException(oauth2Error, ex);
        }
    }

    private OapiUserGetResponse getDDUserInfo(OAuth2UserRequest userRequest, String userId) {
        DingTalkClient client = new DefaultDingTalkClient(userRequest.getClientRegistration().getProviderDetails()
                .getUserInfoEndpoint().getUri());
        OapiUserGetRequest request = new OapiUserGetRequest();
        request.setUserid(userId);
        request.setHttpMethod("GET");
        try {
            return client.execute(request, userRequest.getAccessToken().getTokenValue());
        } catch (ApiException ex) {
            OAuth2Error oauth2Error = new OAuth2Error("invalid_userId_response",
                    "获取钉钉开放平台 getUseridByUnionid Response 异常 : " + ex.getMessage(), null);
            throw new OAuth2AuthorizationException(oauth2Error, ex);
        }
    }

    private String getDDUserId(OAuth2UserRequest userRequest) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getUseridByUnionid");
        OapiUserGetUseridByUnionidRequest request = new OapiUserGetUseridByUnionidRequest();
        request.setUnionid(userRequest.getAdditionalParameters().get("unionid").toString());
        request.setHttpMethod("GET");
        try {
            OapiUserGetUseridByUnionidResponse response = client.execute(request, userRequest.getAccessToken().getTokenValue());
            return response.getUserid();
        } catch (ApiException ex) {
            OAuth2Error oauth2Error = new OAuth2Error("invalid_userId_response",
                    "获取钉钉开放平台 getUseridByUnionid Response 异常 : " + ex.getMessage(), null);
            throw new OAuth2AuthorizationException(oauth2Error, ex);
        }
    }
}
